iT邦幫忙

2021 iThome 鐵人賽

DAY 6
0
Software Development

Rust的多方面運用系列 第 6

[Day6] Vector 使用 以及 迴圈更深應用

  • 分享至 

  • xImage
  •  

今天的內容可能有點雜 進度好慢 zzzz

昨天講到 for loop
但是正常人都不會只是像昨天那樣操作
所以先來講講陣列
let a = [1, 2, 3, 4, 5];
這樣就是一個長度為 5 的陣列
如果只是要初期定義的話可以這樣寫
let a :[i32; 1];
前面的是型態後面則是空間
或者說 要用某個變數填滿他就直接
let a = [5, 1];
創建大小為 1 並且元素皆為 5 的陣列
那這都只是前菜
大部分人(應該)也可以說我,都沒在用陣列的拉
都是直接用 Vector 因為可以動態分配大小,取值的使用又比較方便。
定義如下:
let mut vec = Vec::new();
或者是也可以初始化
let vec2 = Vec::from([1, 2, 3, 4]);
let vec = vec![1, 2, 3, 4];
當然 空間也是可以初始化的
let vec = vec![0; 5];
let vec![0, 0, 0, 0, 0];

那麼以下也是方法,只是較慢 不推薦使用
let mut vec = Vec::with_capacity(5);
vec.resize(5, 0);
至於 Vector 本身除了像 陣列一樣使用還可以幹麻呢
「動態分配空間」
就像 C++ 一樣 使用 push / push_front 即可將要傳入的東西弄到 Vec! 的最尾端 / 最前端
但是這個 Vec 也可以像 stack 一樣取出 top 只要 .top() 就有了
pop 也是把最尾端的丟掉。
那可以延續前面所講的 for loop
可以直接使用 for <AnyName> in <Vector>
這樣得出的結果就類似於使用 C++ 裡面的

for(auto i: vec)

這樣的感覺
來遍歷所有存在 Vector 中的東西
.enumerate()加在迴圈後面可使迴圈的第一個變數為他執行的次數(記數)
ex

for (cnt, index) in vec.iter().enumerate(){

}

這樣可以輕鬆的構造出一個帶編號的 for loop 迴圈
但是問題是
是的 的確能夠正常運行

let a = Vec::from([1, 2, 3]);
for i in a {
    println!("{}", i);
}

但是當重新使用此 Vec 時就會發現由於在 for loop 中 a 的使用權已經被 move 掉了所以無法使用
該怎麼解決?
這時候就要用到之前所講的所有權
clone 一個在迴圈使用時
或者是也可以利用之前稍微提及的"所有權"
& 在 Rust 中意味著借用
這樣講可能沒有這麼好理解

let a = Vec::from([1, 2, 3]);
for i in &a {
    println!("{}", i);
}
println("{}", a[0]);

會發現 他奇蹟的成功了。
因為在 for 迴圈以後就直接將所有權回收回來了。
就不會遇到說後面想要使用時,卻無法使用的問題。
那麼當然,不只是只能用在陣列之中,函數同樣是行得通的
以下是函數的範例

pub fn test(s : &String) {
    println!("{:#}", s);
}

傳入則為

pub fn fn_test() {
    let s = String::from("owo");
    test(&s);
}

那但是 像上面這樣借用出去是可變得嗎?
答案是 不是
其實只要在參數前面加一個 mut 即改為可變 同樣以上面的為範例

pub fn test(s : &mut String) {
    println!("{:#}", s);
}

傳入則為

pub fn fn_test() {
    let mut s = String::from("owo");
    test(&mut s);
}

但是要記得一點,在定義要傳入的參數時,該參數就應該為 可變 了。
那需要記得的是 迴圈的範圍中所定義出的變數在結束迴圈後就會回收,也就是該變數的週期到此為止。
之後如果有機會的話在更新有關生命週期,因為其實我不太熟,主要是生命週期標記的部份。
還有什麼,也是能像 迴圈那樣弄出一個範圍呢?
在 Rust 中恰巧就有兩個:if let 跟 while let
使用範例如下

let a = String::from("123");
if let Some(s) = a {
    println!("{:?}", s); // a 被傳遞給 s 所以後面不能出現 a 了
}

while let 則是

let mut a = Some(0)
while let Some(i) = a {
    if(i > 5) break;
    else {
        i += 1;
    }
}

那到這裡可能就要發問了 Some 是什麼
原本我打算到後面再講 但既然提到了 就來說說吧
Option 這個就是 Rust 用來確保是否有檢查他是 null / none 所開發出來的一個。
而使用 Some 時就是使用他 "確定有值" 的情況。 能夠避免空指標的出現。
也就是在使用後,先做判斷在確定要不要讓他跑下一步。

那這邊來一道練習題
Two Sum

impl Solution {
    pub fn two_sum(nums: Vec<i32>, target: i32) -> Vec<i32> {
        let mut ans: Vec<i32> = Vec::new();
        for (i, num1) in nums.iter().enumerate(){
            for (j, num2) in nums.iter().enumerate(){
                if i == j { continue; }
                if (num1 + num2 == target){
                    ans.push(i as i32);
                    ans.push(j as i32);
                    return ans;
                }
            }
        }
        ans
    }
}

以上 就是今天的內容 有任何問題請提問
可能講述的內容中有些錯誤,也能夠直接糾正 我會虛心接受的!


上一篇
[Day5] 變數&&部份所有權&&簡單的迴圈
下一篇
[Day7] struct 結構體
系列文
Rust的多方面運用30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言